home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / tex-k / tex-k-archive.past / 1994.11.gz / 1994.11 / 000075_rl@leeor.technion.ac.il_Thu Nov 10 10:25:21 1994.msg < prev    next >
Internet Message Format  |  1994-11-30  |  29KB

  1. Received: from leeor.technion.ac.il by cs.umb.edu with SMTP id AA12648
  2.   (5.65c/IDA-1.4.4 for <tex-k@cs.umb.edu>); Thu, 10 Nov 1994 01:25:56 -0500
  3. Received: (from rl@localhost) by leeor.technion.ac.il (8.6.9/8.6.6) id IAA02448; Thu, 10 Nov 1994 08:25:21 +0200
  4. From: "Zvi Har'El" <rl@leeor.technion.ac.il>
  5. Message-Id: <199411100625.IAA02448@leeor.technion.ac.il>
  6. Subject: Re: TeX--XeT and/or working TIE for C
  7. To: Denis.Roegel@loria.fr (Denis B. Roegel)
  8. Date: Thu, 10 Nov 1994 08:25:21 +0200 (EET)
  9. Cc: tex-k@cs.umb.edu, roegel@lorraine.loria.fr
  10. In-Reply-To: <199411091324.OAA26074@pandore.loria.fr> from "Denis B. Roegel" at Nov 9, 94 02:24:04 pm
  11. Hebrew-Date: 7 Kislev 5755 - dpyz'd elqk f
  12. Reply-To: "Zvi Har'El" <rl@leeor.technion.ac.il>
  13. X-Mailer: ELM [version 2.4 PL23]
  14. Mime-Version: 1.0
  15. Content-Type: text/plain; charset=ISO-8859-8
  16. Content-Transfer-Encoding: 8bit
  17. Content-Length: 27161     
  18.  
  19. On Wed Nov  9 15:24:04 1994, Denis B. Roegel wrote about ``TeX--XeT and/or working TIE for C'':
  20. > Can somebody tell me where I can find a TeX--XeT.ch working
  21. > with web2c, and already incoporating the system changes.
  22. Denis,
  23.  
  24. I have a web2c-6.1 version of tex--xet files tex.ch and tex.web.
  25. I generated them using the web2c-5.851d files from noa.huji.ac.il,
  26. taking into account the changes in web2c from 5.851d to 6.1.
  27. I enclose here unified diffs (genrated by gnu diff -U 1),
  28. so you can generate the files using patch.
  29. If you want the files themselves, let me know and I'll put them in our
  30. public ftp directory so you can fetch them.
  31.  
  32. Zvi.
  33. ================================================================================
  34. --- tex.ch.orig    Mon Jul 25 16:31:38 1994
  35. +++ tex.ch    Mon Jul 25 16:34:00 1994
  36. @@ -610,3 +610,3 @@
  37.  @x
  38. -wterm(banner);
  39. +wterm(TeX_XeT_banner);
  40.  if format_ident=0 then wterm_ln(' (no format preloaded)')
  41. @@ -1095,3 +1095,3 @@
  42.  @x
  43. -begin wlog(banner);
  44. +begin wlog(TeX_XeT_banner);
  45.  slow_print(format_ident); print("  ");
  46. @@ -1981,10 +1981,5 @@
  47.  @x
  48. -This section should be replaced, if necessary, by any special
  49. +The following sections, as recommended, contain the more extensive
  50.  modifications of the program
  51.  that are necessary to make \TeX\ work at a particular installation.
  52. -It is usually best to design your change file so that all changes to
  53. -previous sections preserve the section numbering; then everybody's version
  54. -will be consistent with the published program. More extensive changes,
  55. -which introduce new sections, can be inserted here; then only the index
  56. -itself will get a new section number.
  57.  @^system dependencies@>
  58. --- tex.web.orig    Mon Jul 25 16:31:39 1994
  59. +++ tex.web    Mon Jul 25 18:28:20 1994
  60. @@ -44,2 +44,3 @@
  61.  % Version 3.1415 preserved nonexplicit kerns, tidied up (February 1993).
  62. +%   Later this version has been updated by Uri Feldman, to include TeX--XeT.   
  63.  
  64. @@ -60,2 +61,20 @@
  65.  \let\mc=\ninerm % medium caps for names like SAIL
  66. +\font\revmr=xbmc10 % for right-to-left text
  67. +% to generate xbmc10 (i.e., reflected cmbx10) use a file
  68. +% xbmc10.mf containing:
  69. +%+++++++++++++++++++++++++++++++++++++++++++++++++
  70. +%     if unknown cmbase: input cmbase fi
  71. +%     extra_endchar := extra_endchar &
  72. +%       "currentpicture:=currentpicture " &
  73. +%       "reflectedabout((.5[l,r],0),(.5[l,r],1));";
  74. +%     input cmbx10
  75. +%+++++++++++++++++++++++++++++++++++++++++++++++++
  76. +\ifx\beginL\undefined % this is TeX
  77. +  \def\XeT{X\kern-.125em\lower.5ex\hbox{E}\kern-.1667emT}
  78. +  \def\TeXeT{\TeX-\hbox{\revrm \XeT}}      % for TeX-XeT
  79. +  \def\TeXXeT{\TeX-\hbox{\revrm -\XeT}}    % for TeX--XeT
  80. +\else          % this is TeX--XeT (or TeX-XeT)
  81. +  \def\TeXeT{\TeX-{\revrm\beginR\TeX\endR}}      % for TeX-XeT
  82. +  \def\TeXXeT{\TeX-{\revrm\beginR\TeX-\endR}}    % for TeX--XeT
  83. +\fi
  84.  \def\PASCAL{Pascal}
  85. @@ -124,2 +143,5 @@
  86.  
  87. +@d TeX_XeT_version=='--1.0' {identifies the current TeX--XeT version}
  88. +@d TeX_XeT_copyright=='TeX--XeT Copyright (C) 1992 by Dante e.V.'
  89. +
  90.  @ The present implementation has a long ancestry, beginning in the summer
  91. @@ -177,5 +199,28 @@
  92.  
  93. -If this program is changed, the resulting system should not be called
  94. -`\TeX'; the official name `\TeX' by itself is reserved
  95. -for software systems that are fully compatible with each other.
  96. +
  97. +This program contains code for mixed left-to-right and right-to-left
  98. +typesetting. This code is inspired by but different from \TeXeT\ as
  99. +presented by Donald~E. Knuth and Pierre MacKay in {\sl TUGboat\/}
  100. +@^Knuth, Donald Ervin@>
  101. +@^MacKay, Pierre@>
  102. +{\bf 8}, 14--25, 1987. Since the original program is changed, the
  103. +resulting system is not called `\TeX'; the official name `\TeX' by
  104. +itself is reserved for software systems that are fully compatible with
  105. +each other.
  106. +
  107. +In order to avoid confusion with \TeXeT\ the present implementation of
  108. +mixed direction typesetting is called \TeXXeT. It differs from \TeXeT\
  109. +in several important aspects:
  110. +(1)~Right-to-left text is reversed explicitely by the |ship_out| routine
  111. +and is written to a normal \.{DVI} file without any |begin_reflect| or
  112. +|end_reflect| commands; (2)~a |math_node| is (ab)used instead of a
  113. +|whatsit_node| to record the \.{\\beginL}, \.{\\endL}, \.{\\beginR}, and
  114. +\.{\\endR} text direction primitives in order not to influence the line
  115. +breaking algorithm for pure left-to-right text; (3)~therefore \TeXXeT\
  116. +is designed to be used instead of and not in addition to \TeX\ and
  117. +consequently the pool file name is not changed; (4)~right-to-left text
  118. +interrupted by a displayed equation is automatically resumed after that
  119. +equation; and (5)~the |valign| command code with a non-zero command
  120. +modifier is (ab)used for the text direction primitives.
  121. +
  122.  A special test suite called the ``\.{TRIP} test'' is available for
  123. @@ -183,3 +228,3 @@
  124.  known as `\TeX' [cf.~Stanford Computer Science report CS1027,
  125. -November 1984].
  126. +November 1984]. As a consequence of points~(1) and~(2) above \TeXXeT\
  127.  
  128. @@ -218,2 +263,7 @@
  129.  
  130. +@d TeX_XeT_banner=='This is TeX--XeT',
  131. +   ', Version 3.141' {here we should use a substring of banner}
  132. +   ,TeX_XeT_version {printed when \TeX\ starts}
  133. +
  134. +
  135.  @ The program begins with a normal \PASCAL\ program heading, whose
  136. @@ -1554,3 +1604,3 @@
  137.  @<Initialize the output...@>=
  138. -wterm(banner);
  139. +wterm(TeX_XeT_banner);
  140.  if format_ident=0 then wterm_ln(' (no format preloaded)')
  141. @@ -1558,2 +1608,3 @@
  142.    end;
  143. +wterm_ln(TeX_XeT_copyright); {may be omitted under certain circumstances}
  144.  update_terminal;
  145. @@ -3069,2 +3120,6 @@
  146.  
  147. +In addition a |math_node| with |subtype>after| and |width=0| will be
  148. +(ab)used to record one of the text direction primitives ( \.{\\beginL},
  149. +\.{\\endL}, \.{\\beginR}, \.{\\endR} ).
  150. +
  151.  @d math_node=9 {|type| of a math node}
  152. @@ -3072,2 +3127,13 @@
  153.  @d after=1 {|subtype| for math node that winds up a formula}
  154. +@#
  155. +@d L_code=2
  156. +@d begin_L_code=L_code+before {|subtype| for \.{\\beginL} `math node'}
  157. +@d end_L_code=L_code+after {|subtype| for \.{\\endL} `math node'}
  158. +@d R_code=4
  159. +@d begin_R_code=R_code+before {|subtype| for \.{\\beginR} `math node'}
  160. +@d end_R_code=R_code+after {|subtype| for \.{\\endR} `math node'}
  161. +@#
  162. +@d end_LR(#)==odd(subtype(#))
  163. +@d end_LR_type(#)==(subtype(#)+after-before)
  164. +@d begin_LR_type(#)==(info(#)-after+before)
  165.  
  166. @@ -3544,3 +3610,4 @@
  167.  glue_node: if glue_ptr(p)<>zero_glue then print_char(" ");
  168. -math_node: print_char("$");
  169. +math_node: if subtype(p)>after then print("[]")
  170. +  else print_char("$");
  171.  ligature_node: short_display(lig_ptr(p));
  172. @@ -3809,3 +3876,9 @@
  173.  @ @<Display math node |p|@>=
  174. -begin print_esc("math");
  175. +if subtype(p)>after then
  176. +  begin if odd(subtype(p)) then print_esc("end")
  177. +  else print_esc("begin");
  178. +  if subtype(p)<=end_L_code then print_char("L")
  179. +  else print_char("R");
  180. +  end
  181. +else begin print_esc("math");
  182.  if subtype(p)=before then print("on")
  183. @@ -4089,3 +4162,4 @@
  184.  @d halign=32 {horizontal table alignment ( \.{\\halign} )}
  185. -@d valign=33 {vertical table alignment ( \.{\\valign} )}
  186. +@d valign=33 {vertical table alignment ( \.{\\valign} ) or text
  187. +    direction ( \.{\\beginL}, \.{\\endL}, \.{\\beginR}, \.{\\endR} )}
  188.  @d no_align=34 {temporary escape from alignment ( \.{\\noalign} )}
  189. @@ -4290,2 +4364,4 @@
  190.  In horizontal mode, the |prev_graf| field is used for initial language data.
  191. +A nineth quantity, |LR_save|, holds the LR stack when a paragraph is
  192. +interrupted by a displayed formula.
  193.  
  194. @@ -4305,2 +4381,3 @@
  195.    @!aux_field: memory_word;
  196. +  @!LRs_field: halfword;
  197.    end;
  198. @@ -4317,2 +4394,3 @@
  199.  @d mode_line==cur_list.ml_field {source file line number at beginning of list}
  200. +@d LR_save==cur_list.LRs_field {LR stack when a paragraph is interrupted}
  201.  
  202. @@ -4342,2 +4420,3 @@
  203.  prev_depth:=ignore_depth; mode_line:=0;
  204. +LR_save:=null;
  205.  prev_graf:=0; shown_mode:=0;
  206. @@ -4357,2 +4436,3 @@
  207.  incr(nest_ptr); head:=get_avail; tail:=head; prev_graf:=0; mode_line:=line;
  208. +LR_save:=null;
  209.  end;
  210. @@ -5712,2 +5792,10 @@
  211.  @!@:valign_}{\.{\\valign} primitive@>
  212. +primitive("beginL",valign,begin_L_code);@/
  213. +@!@:beginL_}{\.{\\beginL} primitive@>
  214. +primitive("endL",valign,end_L_code);@/
  215. +@!@:endL_}{\.{\\endL} primitive@>
  216. +primitive("beginR",valign,begin_R_code);@/
  217. +@!@:beginR_}{\.{\\beginR} primitive@>
  218. +primitive("endR",valign,end_R_code);@/
  219. +@!@:endR_}{\.{\\endR} primitive@>
  220.  primitive("vcenter",vcenter,0);@/
  221. @@ -5764,3 +5852,9 @@
  222.  vadjust: print_esc("vadjust");
  223. -valign: print_esc("valign");
  224. +valign: if chr_code<>0 then case chr_code of
  225. +  begin_L_code: print_esc("beginL");
  226. +  end_L_code: print_esc("endL");
  227. +  begin_R_code: print_esc("beginR");
  228. +  othercases print_esc("endR")
  229. +  endcases
  230. +else print_esc("valign");
  231.  vcenter: print_esc("vcenter");
  232. @@ -10322,3 +10416,3 @@
  233.  @ @<Print the banner...@>=
  234. -begin wlog(banner);
  235. +begin wlog(TeX_XeT_banner);
  236.  slow_print(format_ident); print("  ");
  237. @@ -12238,3 +12332,25 @@
  238.  
  239. -@d synch_h==if cur_h<>dvi_h then
  240. +For mixed direction text (\TeXXeT) the current text direction is called
  241. +|cur_dir|. As the box being shipped out will never be used again and
  242. +soon be recycled, we can simply reverse any R-text (i.e., right-to-left)
  243. +segments of hlist nodes as well as complete hlist nodes embedded in such
  244. +segments. Moreover this can be done iteratively rather than recursively.
  245. +There are, however, two complications related to leaders which require
  246. +some additional bookkeeping: (1)~One and the same hlist node might be
  247. +used more than once (but never inside both L- and R-text); and
  248. +(2)~leader boxes inside hlists must be aligned with respect to the left
  249. +edge of the original hlist.
  250. +
  251. +A math node is changed into a kern node whenever the text direction
  252. +remains the same, it is replaced by an |edge_node| if the text direction
  253. +changes; an |hlist_node| inside R-text is changed to an |R_node| once
  254. +its hlist has been reversed.
  255. +@!@^data structure assumptions@>
  256. +
  257. +    @d R_node=unset_node {an |unset_node| does not occur during |ship_out|}
  258. +    @d left_to_right=0
  259. +    @d right_to_left=1
  260. +    @d reflected==1-cur_dir {the opposite of |cur_dir|}
  261. +    @#
  262. +    @d synch_h==if cur_h<>dvi_h then
  263.      begin movement(cur_h-dvi_h,right1); dvi_h:=cur_h;
  264. @@ -12250,2 +12366,4 @@
  265.  @!cur_s:integer; {current depth of output box nesting, initially $-1$}
  266. +@!cur_dir:small_number; {current text direction}
  267. +@!LR_ptr:pointer; {stack of LR codes}
  268.  
  269. @@ -12306,3 +12424,4 @@
  270.  @!outer_doing_leaders:boolean; {were we doing leaders?}
  271. -@!edge:scaled; {left edge of sub-box, or right edge of leader space}
  272. +@!edge:scaled; {right edge of sub-box or leader space}
  273. +@!prev_p:pointer; {one step behind |p|}
  274.  begin this_box:=temp_ptr; g_order:=glue_order(this_box);
  275. @@ -12313,2 +12432,5 @@
  276.  save_loc:=dvi_offset+dvi_ptr; base_line:=cur_v; left_edge:=cur_h;
  277. +prev_p:=this_box+list_offset;
  278. +if cur_dir=right_to_left then if type(this_box)=hlist_node then
  279. +  @<Reverse the complete hlist and change this node into an |R_node|@>;
  280.  while p<>null do @<Output node |p| for |hlist_out| and move to the next node,
  281. @@ -12334,3 +12456,3 @@
  282.    cur_h:=cur_h+char_width(f)(char_info(f)(c));
  283. -  p:=link(p);
  284. +  prev_p:=p; p:=link(p);
  285.    until not is_char_node(p);
  286. @@ -12353,3 +12475,3 @@
  287.  begin case type(p) of
  288. -hlist_node,vlist_node:@<Output a box in an hlist@>;
  289. +hlist_node,vlist_node,R_node:@<Output a box in an hlist@>;
  290.  rule_node: begin rule_ht:=height(p); rule_dp:=depth(p); rule_wd:=width(p);
  291. @@ -12359,4 +12481,10 @@
  292.  glue_node: @<Move right or output leaders@>;
  293. -kern_node,math_node:cur_h:=cur_h+width(p);
  294. +kern_node:cur_h:=cur_h+width(p);
  295. +math_node:
  296. +  begin @<Adjust the LR stack for the |ship_out| routine; if necessary
  297. +    reverse an hlist segment and |goto reswitch||@>;
  298. +  cur_h:=cur_h+width(p);
  299. +  end;
  300.  ligature_node: @<Make node |p| look like a |char_node| and |goto reswitch|@>;
  301. +@<Cases of |hlist_out| that arise in mixed direction text only@>@;
  302.  othercases do_nothing
  303. @@ -12366,3 +12494,3 @@
  304.  move_past: cur_h:=cur_h+rule_wd;
  305. -next_p:p:=link(p);
  306. +next_p:prev_p:=p; p:=link(p);
  307.  end
  308. @@ -12373,6 +12501,7 @@
  309.    cur_v:=base_line+shift_amount(p); {shift the box down}
  310. -  temp_ptr:=p; edge:=cur_h;
  311. +  temp_ptr:=p; edge:=cur_h+width(p);
  312. +  if cur_dir=right_to_left then cur_h:=edge;
  313.    if type(p)=vlist_node then vlist_out@+else hlist_out;
  314.    dvi_h:=save_h; dvi_v:=save_v;
  315. -  cur_h:=edge+width(p); cur_v:=base_line;
  316. +  cur_h:=edge; cur_v:=base_line;
  317.    end
  318. @@ -12416,2 +12545,3 @@
  319.    begin rule_wd:=rule_wd+10; {compensate for floating-point rounding}
  320. +  if cur_dir=right_to_left then cur_h:=cur_h-10;
  321.    edge:=cur_h+rule_wd; lx:=0;
  322. @@ -12422,3 +12552,5 @@
  323.        then advance |cur_h| by |leader_wd+lx|@>;
  324. -  cur_h:=edge-10; goto next_p;
  325. +    if cur_dir=right_to_left then cur_h:=edge
  326. +    else cur_h:=edge-10;
  327. +    goto next_p;
  328.    end;
  329. @@ -12462,2 +12594,3 @@
  330.  synch_h; save_h:=dvi_h; temp_ptr:=leader_box;
  331. +if cur_dir=right_to_left then cur_h:=cur_h+leader_wd;
  332.  outer_doing_leaders:=doing_leaders; doing_leaders:=true;
  333. @@ -12509,3 +12642,3 @@
  334.  begin case type(p) of
  335. -hlist_node,vlist_node:@<Output a box in a vlist@>;
  336. +hlist_node,vlist_node,R_node:@<Output a box in a vlist@>;
  337.  rule_node: begin rule_ht:=height(p); rule_dp:=depth(p); rule_wd:=width(p);
  338. @@ -12531,3 +12664,4 @@
  339.    save_h:=dvi_h; save_v:=dvi_v;
  340. -  cur_h:=left_edge+shift_amount(p); {shift the box right}
  341. +  if cur_dir=right_to_left then cur_h:=left_edge-shift_amount(p)
  342. +  else cur_h:=left_edge+shift_amount(p); {shift the box right}
  343.    temp_ptr:=p;
  344. @@ -12543,3 +12677,6 @@
  345.  if (rule_ht>0)and(rule_wd>0) then {we don't output empty rules}
  346. -  begin synch_h; synch_v;
  347. +  begin if cur_dir=right_to_left then cur_h:=cur_h-rule_wd;
  348. +  synch_h; synch_v;
  349. +  dvi_out(put_rule); dvi_four(rule_ht); dvi_four(rule_wd);
  350. +  cur_h:=left_edge;
  351.    dvi_out(put_rule); dvi_four(rule_ht); dvi_four(rule_wd);
  352. @@ -12640,3 +12777,7 @@
  353.    end;
  354. +cur_dir:=left_to_right; {L-text at the outer level}
  355. +LR_ptr:=get_avail; info(LR_ptr):=before; {this will never match}
  356.  @<Ship box |p| out@>;
  357. +if info(LR_ptr)<>before then LR_confusion;
  358. +free_avail(LR_ptr); LR_ptr:=null;
  359.  if tracing_output<=0 then print_char("]");
  360. @@ -12846,3 +12987,7 @@
  361.  
  362. -@p function hpack(@!p:pointer;@!w:scaled;@!m:small_number):pointer;
  363. +@p function safe_info(@!p:pointer): halfword;
  364. +begin if p=null then safe_info:=0@+else safe_info:=info(p);
  365. +end;
  366. +@#
  367. +function hpack(@!p:pointer;@!w:scaled;@!m:small_number):pointer;
  368.  label reswitch, common_ending, exit;
  369. @@ -12857,3 +13002,6 @@
  370.  @!hd:eight_bits; {height and depth indices for a character}
  371. -begin last_badness:=0; r:=get_node(box_node_size); type(r):=hlist_node;
  372. +@!LR_ptr:pointer; {stack of LR codes}
  373. +@!LR_problems:integer; {counts missing begins and ends}
  374. +begin LR_ptr:=null; LR_problems:=0;
  375. +last_badness:=0; r:=get_node(box_node_size); type(r):=hlist_node;
  376.  subtype(r):=min_quarterword; shift_amount(r):=0;
  377. @@ -12870,3 +13018,4 @@
  378.        for an overfull or underfull hbox@>;
  379. -exit: hpack:=r;
  380. +exit: @<Check for LR anomalies at the end of |hpack|@>;
  381. +hpack:=r;
  382.  end;
  383. @@ -12894,3 +13043,6 @@
  384.    glue_node:@<Incorporate glue into the horizontal totals@>;
  385. -  kern_node,math_node: x:=x+width(p);
  386. +  kern_node,math_node:
  387. +    begin x:=x+width(p);
  388. +    @<Adjust the LR stack for the |hpack| routine@>;
  389. +    end;
  390.    ligature_node: @<Make node |p| look like a |char_node|
  391. @@ -17014,3 +17166,3 @@
  392.  disc_node: @<Try to break after a discretionary fragment, then |goto done5|@>;
  393. -math_node: begin auto_breaking:=(subtype(cur_p)=after); kern_break;
  394. +  math_node: begin auto_breaking:=(subtype(cur_p)<>before); kern_break;
  395.    end;
  396. @@ -17200,3 +17352,5 @@
  397.  @!cur_line: halfword; {the current line number being justified}
  398. -begin @<Reverse the links of the relevant passive nodes, setting |cur_p| to the
  399. +  @!LR_ptr:pointer; {stack of LR codes}
  400. +  begin LR_ptr:=LR_save;
  401. +  @<Reverse the links of the relevant passive nodes, setting |cur_p| to the
  402.    first breakpoint@>;
  403. @@ -17213,3 +17367,3 @@
  404.  @:this can't happen line breaking}{\quad line breaking@>
  405. -prev_graf:=best_line-1;
  406. +prev_graf:=best_line-1; LR_save:=LR_ptr;
  407.  end;
  408. @@ -17243,3 +17397,4 @@
  409.    if type(q)=kern_node then if subtype(q)<>explicit then goto done1;
  410. -  r:=q; {now |type(q)=glue_node|, |kern_node|, |math_node| or |penalty_node|}
  411. +    r:=q; {now |type(q)=glue_node|, |kern_node|, |math_node| or |penalty_node|}
  412. +    @<Adjust the LR stack for the |post_line_break| routine@>;
  413.    end;
  414. @@ -17260,4 +17415,7 @@
  415.  @<Justify the line ending at breakpoint |cur_p|, and append it...@>=
  416. +@<Insert LR nodes at the beginning of the current line and adjust
  417. +  the LR stack based on LR nodes in this line@>;
  418.  @<Modify the end of the line to reflect the nature of the break and to include
  419.    \.{\\rightskip}; also set the proper value of |disc_break|@>;
  420. +@<Insert LR nodes at the end of the current line@>;
  421.  @<Put the \(l)\.{\\leftskip} glue at the left and detach this line@>;
  422. @@ -17283,3 +17441,5 @@
  423.          |disc_break:=true|@>
  424. -    else if (type(q)=math_node)or(type(q)=kern_node) then width(q):=0;
  425. +      else if (type(q)=math_node)or(type(q)=kern_node) then
  426. +        begin width(q):=0; @<Adjust the LR stack for the |p...@>;
  427. +        end;
  428.      end
  429. @@ -21104,2 +21264,5 @@
  430.    else line_break(widow_penalty);
  431. +  if LR_save<>null then
  432. +    begin flush_list(LR_save); LR_save:=null;
  433. +    end;
  434.    normal_paragraph;
  435. @@ -21546,3 +21709,5 @@
  436.  @<Cases of |main_control| that build...@>=
  437. -vmode+halign,hmode+valign:init_align;
  438. +vmode+halign,hmode+valign:
  439. +  if cur_chr>0 then tail_append(new_math(0,cur_chr))
  440. +  else init_align;
  441.  mmode+halign: if privileged then
  442. @@ -24882,11 +25047,258 @@
  443.  @* \[54] System-dependent changes.
  444. -This section should be replaced, if necessary, by any special
  445. +The following sections, as recommended, contain the more extensive
  446.  modifications of the program
  447.  that are necessary to make \TeX\ work at a particular installation.
  448. -It is usually best to design your change file so that all changes to
  449. -previous sections preserve the section numbering; then everybody's version
  450. -will be consistent with the published program. More extensive changes,
  451. -which introduce new sections, can be inserted here; then only the index
  452. -itself will get a new section number.
  453.  @^system dependencies@>
  454. +
  455. +@ Insert system dependent changes here.
  456. +
  457. +@ Last not least we do the main work required for mixed-direction texts.
  458. +A number of routines are based on a stack of one-word nodes whose |info|
  459. +fields contain |after|, |end_L_code|, or |end_R_code|. The top of the
  460. +stack is pointed to by |LR_ptr|.
  461. +
  462. +When the stack_manipulation macros of this section are used below,
  463. +variable |LR_ptr| might be the global variable declared for |ship_out|,
  464. +or might be local to |hpack| or |post_line_break|.
  465. +
  466. +@d push_LR(#)==begin temp_ptr:=get_avail; info(temp_ptr):=end_LR_type(#);
  467. +  link(temp_ptr):=LR_ptr; LR_ptr:=temp_ptr;
  468. +  end
  469. +@d pop_LR==begin temp_ptr:=LR_ptr; LR_ptr:=link(temp_ptr);
  470. +  free_avail(temp_ptr);
  471. +  end
  472. +
  473. +@<Insert LR nodes at the beg...@>=
  474. +q:=link(temp_head);
  475. +if LR_ptr<>null then
  476. +  begin temp_ptr:=LR_ptr; r:=q;
  477. +  repeat s:=new_math(0,begin_LR_type(temp_ptr)); link(s):=r; r:=s;
  478. +  temp_ptr:=link(temp_ptr);
  479. +  until temp_ptr=null;
  480. +  link(temp_head):=r;
  481. +  end;
  482. +while q<>cur_break(cur_p) do
  483. +  begin if not is_char_node(q) then @<Adjust the LR stack for the |p...@>;
  484. +  q:=link(q);
  485. +  end
  486. +
  487. +@ @<Adjust the LR stack for the |p...@>=
  488. +if type(q)=math_node then
  489. +  if end_LR(q) then
  490. +    begin if LR_ptr<>null then if info(LR_ptr)=subtype(q) then pop_LR;
  491. +    end
  492. +  else push_LR(q)
  493. +
  494. +@ We use the fact that |q| now points to the node with \.{\\rightskip} glue.
  495. +
  496. +@<Insert LR nodes at the end...@>=
  497. +if LR_ptr<>null then
  498. +  begin s:=temp_head; r:=link(s);
  499. +  while r<>q do
  500. +    begin s:=r; r:=link(s);
  501. +    end;
  502. +  r:=LR_ptr;
  503. +  while r<>null do
  504. +    begin temp_ptr:=new_math(0,info(r));
  505. +    link(s):=temp_ptr; s:=temp_ptr; r:=link(r);
  506. +    end;
  507. +  link(s):=q;
  508. +  end
  509. +
  510. +@ @<Adjust the LR stack for the |h...@>=
  511. +if type(p)=math_node then
  512. +  if end_LR(p) then
  513. +    if safe_info(LR_ptr)=subtype(p) then pop_LR
  514. +    else  begin incr(LR_problems);
  515. +      while link(q)<>p do q:=link(q);
  516. +      link(q):=link(p); free_node(p,small_node_size); p:=q;
  517. +      end
  518. +  else push_LR(p)
  519. +
  520. +@ @<Check for LR anomalies at the end of |h...@>=
  521. +if LR_ptr<>null then
  522. +  begin while link(q)<>null do q:=link(q);
  523. +  repeat temp_ptr:=q; q:=new_math(0,info(LR_ptr)); link(temp_ptr):=q;
  524. +  LR_problems:=LR_problems+10000; pop_LR;
  525. +  until LR_ptr=null;
  526. +  end;
  527. +if LR_problems>0 then
  528. +  begin print_ln; print_nl("\endL or \endR problem (");@/
  529. +  print_int(LR_problems div 10000); print(" missing, ");@/
  530. +  print_int(LR_problems mod 10000); print(" extra");@/
  531. +  LR_problems:=0; goto common_ending;
  532. +  end
  533. +
  534. +@ @<Declare procedures needed in |hlist_out|, |vlist_out|@>=
  535. +procedure LR_confusion;
  536. +begin confusion("LR");
  537. +@:this can't happen LR}{\quad LR@>
  538. +end;
  539. +
  540. +@ @d LR_dir(#)==(subtype(#) div 4) {text direction of a `math node'}
  541. +
  542. +@<Adjust the LR stack for the |s...@>=
  543. +if end_LR(p) then
  544. +  begin if info(LR_ptr)<>subtype(p) then LR_confusion;
  545. +  pop_LR; type(p):=kern_node;
  546. +  end
  547. +else  begin push_LR(p); type(p):=kern_node;
  548. +  if LR_dir(p)<>cur_dir then
  549. +    begin @<Reverse an hlist segment containing right-to-left material@>;
  550. +    goto reswitch;
  551. +    end;
  552. +  type(p):=kern_node;
  553. +  end
  554. +
  555. +@ @d edge_node=style_node {a |style_node| does not occur during |ship_out|}
  556. +@d edge_node_size=style_node_size {number of words in an edge node}
  557. +@d edge_dist(#)==depth(#) {new |left_edge| position relative to |cur_h|
  558. +   (after |width| has been taken into account)}
  559. +
  560. +@<Declare procedures needed in |hlist_out|, |vlist_out|@>=
  561. +function new_edge(@!s:small_number;@!w:scaled):pointer;
  562. +  {create an edge node}
  563. +var p:pointer; {the new node}
  564. +begin p:=get_node(edge_node_size); type(p):=edge_node;
  565. +subtype(p):=s; width(p):=w; {the |edge_dist| field will be set later}
  566. +new_edge:=p;
  567. +end;
  568. +
  569. +@ @<Cases of |hlist_out| that arise...@>=
  570. +edge_node: begin cur_h:=cur_h+width(p);
  571. +  left_edge:=cur_h+edge_dist(p); cur_dir:=subtype(p);
  572. +  end;
  573. +
  574. +@ We detach the hlist, start a new one consisting of just one kern node,
  575. +append the reversed list, and set the width of the kern node.
  576. +
  577. +@<Reverse the complete hlist...@>=
  578. +begin save_h:=cur_h; temp_ptr:=p; p:=new_kern(0); link(prev_p):=p;
  579. +cur_h:=0; link(p):=reverse(this_box,null); width(p):=-cur_h;
  580. +cur_h:=save_h; type(this_box):=R_node;
  581. +end
  582. +
  583. +@ We detach the remainder of the hlist, replace the math node by
  584. +an edge node, and append the reversed hlist segment to it; the tail of
  585. +the reversed segment is another edge node and the remainder of the
  586. +original list is attached to it.
  587. +
  588. +@<Reverse an hlist segment...@>=
  589. +begin save_h:=cur_h; temp_ptr:=link(p); rule_wd:=width(p);
  590. +free_node(p,small_node_size);
  591. +cur_dir:=reflected; p:=new_edge(cur_dir,rule_wd); link(prev_p):=p;
  592. +cur_h:=cur_h-left_edge+rule_wd;
  593. +link(p):=reverse(this_box,new_edge(reflected,0));
  594. +edge_dist(p):=cur_h; cur_dir:=reflected; cur_h:=save_h;
  595. +end
  596. +
  597. +@ The |reverse| function defined here is responsible to reverse the
  598. +nodes of an hlist (segment). The first parameter |this_box| is the
  599. +enclosing hlist node, the second parameter |t| is to become the tail of
  600. +the reversed list, and the global variable |temp_ptr| is the head of the
  601. +list to be reversed. We remove nodes from the original list and add them
  602. +to the head of the new one.
  603. +
  604. +@<Declare procedures needed in |hlist_out|, |vlist_out|@>=
  605. +function reverse(@!this_box,@!t:pointer):pointer;
  606. +label reswitch, next_p, done;
  607. +var l:pointer; {the new list}
  608. +@!p:pointer; {the current node}
  609. +@!q:pointer; {the next node}
  610. +@!g_order: glue_ord; {applicable order of infinity for glue}
  611. +@!g_sign: normal..shrinking; {selects type of glue}
  612. +@!m,@!n:halfword; {number of unmatched math nodes}
  613. +begin g_order:=glue_order(this_box); g_sign:=glue_sign(this_box);
  614. +l:=t; p:=temp_ptr; m:=min_halfword; n:=min_halfword;
  615. +while p<>null do @<Move node |p| to the new list and go to the next node;
  616. +  or |goto done| if the end of the reflected segment has been reached@>;
  617. +if (t<>null)or(m<>min_halfword)or(n<>min_halfword) then LR_confusion;
  618. +done:reverse:=l;
  619. +end;
  620. +
  621. +@ @<Move node |p| to the new list...@>=
  622. +reswitch: if is_char_node(p) then
  623. +  repeat f:=font(p); c:=character(p);
  624. +  cur_h:=cur_h+char_width(f)(char_info(f)(c));
  625. +  q:=link(p); link(p):=l; l:=p; p:=q;
  626. +  until not is_char_node(p)
  627. +else @<Move the non-|char_node| |p| to the new list@>
  628. +
  629. +@ @<Move the non-|char_node| |p| to the new list@>=
  630. +begin q:=link(p); rule_wd:=width(p); {the width is needed in most cases}
  631. +case type(p) of
  632. +hlist_node,vlist_node,rule_node,kern_node: do_nothing;
  633. +@t\4@>@<Cases of |reverse| that need special treatment@>@;
  634. +R_node,edge_node: LR_confusion;
  635. +othercases goto next_p
  636. +endcases;@/
  637. +cur_h:=cur_h+rule_wd;
  638. +next_p: if (type(p)=kern_node)and((rule_wd=0)or(l=null)) then
  639. +  free_node(p,small_node_size)
  640. +else  begin link(p):=l; l:=p;
  641. +  end;
  642. +p:=q;
  643. +end
  644. +
  645. +@ In order to avoid the unnecessary repetition of computations we try to
  646. +replace glue nodes by equivalent kern or rule nodes.
  647. +
  648. +@<Cases of |reverse|...@>=
  649. +glue_node: begin g:=glue_ptr(p); rule_wd:=width(g);
  650. +if g_sign<>normal then
  651. +  begin if g_sign=stretching then
  652. +    begin if stretch_order(g)=g_order then
  653. +      rule_wd:=rule_wd+round(float(glue_set(this_box))*stretch(g));
  654. +@^real multiplication@>
  655. +    end
  656. +  else  begin if shrink_order(g)=g_order then
  657. +      rule_wd:=rule_wd-round(float(glue_set(this_box))*shrink(g));
  658. +    end;
  659. +  end;
  660. +temp_ptr:=leader_ptr(p);
  661. +if temp_ptr=null then
  662. +  begin delete_glue_ref(g); type(p):=kern_node; width(p):=rule_wd;
  663. +  end
  664. +else if type(temp_ptr)=rule_node then
  665. +  begin delete_glue_ref(g); free_node(p,small_node_size);
  666. +  p:=temp_ptr; width(p):=rule_wd;
  667. +  end;
  668. +end;
  669. +
  670. +@ A ligature node is replaced by a char node.
  671. +
  672. +@<Cases of |reverse|...@>=
  673. +ligature_node: begin flush_node_list(lig_ptr(p));
  674. +temp_ptr:=p; p:=get_avail; mem[p]:=mem[lig_char(temp_ptr)]; link(p):=q;
  675. +free_node(temp_ptr,small_node_size); goto reswitch;
  676. +end;
  677. +
  678. +@ Math nodes in an inner reflected segment are modified, those at the
  679. +outer level are changed into kern nodes.
  680. +
  681. +@<Cases of |reverse|...@>=
  682. +math_node: if end_LR(p) then
  683. + if n>min_halfword then
  684. +  begin decr(n); decr(subtype(p)); {change |after| into |before|}
  685. +  end
  686. + else begin if info(LR_ptr)<>subtype(p) then LR_confusion;
  687. +  pop_LR;
  688. +  if m=min_halfword then @<Finish the reversed list and |goto done|@>;
  689. +  decr(m); type(p):=kern_node;
  690. +  end
  691. +else if (n>min_halfword)or(LR_dir(p)<>cur_dir) then
  692. +  begin incr(n); incr(subtype(p)); {change |before| into |after|}
  693. +  end
  694. + else begin push_LR(p); incr(m); type(p):=kern_node;
  695. +  end;
  696. +
  697. +@ Finally we have found the end of the hlist segment to be reversed; the
  698. +terminating math node is released and the remaining list is attached to
  699. +the edge node at the end of the reversed list.
  700. +
  701. +@<Finish the reversed list and |goto done|@>=
  702. +begin if t=null then LR_confusion; free_node(p,small_node_size);
  703. +link(t):=q; width(t):=rule_wd; edge_dist(t):=-cur_h-rule_wd;
  704. +goto done;
  705. +end
  706.  
  707. -- 
  708. Dr. Zvi Har'El <rl@math.technion.ac.il>                Department of Mathematics
  709. +972-4-294094(Phone)                   Technion - Israel Institute of Technology
  710. +972-4-324654(FAX)                                           Haifa 32000, ISRAEL
  711. ``If you can't say somethin' nice, don't say nothin' at all.'' -- Thumper (1942)